package com.app.system.utils.dataType;

import com.app.system.utils.exception.Precondition;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.util.Calendar;
import java.util.Date;

/**
 * Created by wcf-pc on 2018/4/17.
 *
 * @author wcf-pc
 */
@SuppressWarnings("all")
public class DateUtils {

    /**
     * 字符串转日期格式
     *
     * @param dateStr
     */
    public static Date stringToDateDefault(String dateStr) {
        if (dateStr == null) {
            return null;
        }
        return stringToDateFormat(dateStr, "yyyy-MM-dd");
    }

    /**
     * 日期转字符串格式
     *
     * @param date
     */
    public static String dateToStringDefault(Date date) {
        if (date == null) {
            return null;
        }
        return dateToStringFormat(date, "yyyy-MM-dd");
    }

    /**
     * 日期转字符串格式
     *
     * @param date
     */
    public static String dateToStringDefaultForPoint(Date date) {
        if (date == null) {
            return null;
        }
        return dateToStringFormat(date, "yyyy.MM.dd");
    }

    /**
     * 日期转字符串格式
     *
     * @param date
     */
    public static String dateToStringDefaultForSecond(Date date) {
        if (date == null) {
            return null;
        }
        return dateToStringFormat(date, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 日期格式化输出（字符串）
     *
     * @param date
     * @param pattern
     * @return
     */
    public static String dateToStringFormat(Date date, String pattern) {
        SimpleDateFormat format = new SimpleDateFormat(pattern);
        return format.format(date);
    }

    /**
     * 日期格式化输出（字符串）
     * long类型转换
     *
     * @param dateLong
     * @param pattern
     * @return
     */
    public static String dateToStringFormat(Long dateLong, String pattern) {
        SimpleDateFormat format = new SimpleDateFormat(pattern);
        return format.format(dateLong);
    }

    /**
     * 日期格式化输出（日期）
     *
     * @param dateString
     * @param pattern
     * @return
     */
    public static Date stringToDateFormat(String dateString, String pattern) {
        SimpleDateFormat format = new SimpleDateFormat(pattern);
        try {
            return format.parse(dateString);
        } catch (ParseException e) {
        }
        return null;
    }

    /**
     * 计算两个日期之间的天数
     * 天数跟时间无关（如2018-01-01 23：59：59.000 和 2018-01-02：00：00.000一样，返回结果一样）
     * startDate 须在endDate 之前
     *
     * @param startDate
     * @param endDate
     * @return
     * @throws ParseException
     */
    public static Integer getBetweenDays(Date startDate, Date endDate) throws ParseException {
        Integer day = 0;
        //非空判断
        String param = "";
        if (startDate != null && endDate != null && !param.equals(startDate) && !param.equals(endDate)) {
            Precondition.checkAjaxArguement(!startDate.after(endDate), "0000", "startDate须在endDate之前");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Calendar startTime = Calendar.getInstance();
            Calendar endTime = Calendar.getInstance();
            startTime.setTime(sdf.parse(sdf.format(startDate)));
            endTime.setTime(sdf.parse(sdf.format(endDate)));
            long betweenTime = endTime.getTimeInMillis() - startTime.getTimeInMillis();
            long date =  betweenTime / (24 * 60 * 60 * 1000);
            day = (int) date;
        }
        return day;
    }

    /**
     * 计算两个日期之间的天数
     * 天数跟时间无关（如2018-01-01 23：59：59.000 和 2018-01-02：00：00.000一样，返回结果一样）
     * startDate 须在endDate 之前
     *
     * @param startDate
     * @param endDate
     * @return
     * @throws ParseException
     */
    public static Integer getBetweenSeconds(Date startDate, Date endDate) throws ParseException {
        Integer secondsResult = 0;
        //非空判断
        String param = "";
        if (startDate != null && endDate != null && !param.equals(startDate) && !param.equals(endDate)) {
            Precondition.checkAjaxArguement(!startDate.after(endDate), "0000", "startDate须在endDate之前");
            // 开始时间
            LocalDateTime startTime = DateUtils.asLocalDateTime(startDate);
            // 结束时间
            LocalDateTime endTime = DateUtils.asLocalDateTime(endDate);
            // 差
            Duration duration = Duration.between(startTime, endTime);
            // 相差的秒数
            long seconds = duration.toMillis() / 1000;
            secondsResult = (int) seconds;
        }
        return secondsResult;
    }

    /**
     * 获取当前前几天日期
     *
     * @param past
     * @return yyyy-MM-dd
     */
    public static String getPastDate(int past) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) - past);
        Date today = calendar.getTime();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String result = format.format(today);
        return result;
    }

    /**
     * 根据输入日期获取其前几天日期
     *
     * @param str  yyyy-MM-dd
     * @param past
     * @return yyyy-MM-dd
     */
    public static String getPastDate(String str, int past) {
        Calendar c = Calendar.getInstance();
        Date date = null;
        try {
            date = new SimpleDateFormat("yy-MM-dd").parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        c.setTime(date);
        int day = c.get(Calendar.DATE);
        c.set(Calendar.DATE, day - past);

        String dayBefore = new SimpleDateFormat("yyyy-MM-dd").format(c.getTime());
        return dayBefore;
    }

    /**
     * 计算日期间相隔天数
     *
     * @param startTime yyyy-MM-dd 开始日期
     * @param endTime   yyyy-MM-dd 结束日期
     * @return
     */
    public static Integer dateApart(String startTime, String endTime) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date date1 = format.parse(endTime);
            Date date2 = format.parse(startTime);
            int a = (int) ((date1.getTime() - date2.getTime()) / (1000 * 3600 * 24));
            return a;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 获取几天后的日期
     *
     * @param after
     * @return
     */
    public static String getAfterData(int after) {
        Long time = System.currentTimeMillis();
        time += after * 1000 * 60 * 60 * 24L;
        return formateTime(time, "yyyy-MM-dd");
    }


    public static String formateTime(Long time, String format) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        return simpleDateFormat.format(new Date(time));
    }


    /**
     * 获取制定日期后的几天
     *
     * @param str
     * @param after
     * @return
     */
    public static String getAfterData(String str, int after) {
        try {
            Date date = new SimpleDateFormat("yyyy-MM-dd").parse(str);
            Long time = date.getTime();
            time += after * 1000 * 60 * 60 * 24L;
            return formateTime(time, "yyyy-MM-dd");
        } catch (ParseException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 根据输入天数获取几天前时间
     *
     * @param days 几天前
     * @return yyyy-MM-dd
     */
    public static String getBeforeTimeByDays(int days) {
        //现在
        LocalDateTime localDateTime = LocalDateTime.now();
        //days天前
        LocalDateTime firstLocalDateTime = localDateTime.minusDays(days);
        int year = firstLocalDateTime.getYear();
        int month = firstLocalDateTime.getMonth().getValue();
        int day = firstLocalDateTime.getDayOfMonth();
        String firstDay = year + "-" + (month >= 10 ? month : "0" + month) + "-" + (day >= 10 ? day : "0" + day);
        return firstDay;
    }

    /**
     * LocalDate -> Date
     * @param localDate
     * @return
     */
    public static Date asDate(LocalDate localDate) {
        return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * LocalDateTime -> Date
     * @param localDateTime
     * @return
     */
    public static Date asDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * Date -> LocalDate
     * @param date
     * @return
     */
    public static LocalDate asLocalDate(Date date) {
        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
    }

    /**
     * Date -> LocalDateTime
     * @param date
     * @return
     */
    public static LocalDateTime asLocalDateTime(Date date) {
        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    /**
     * String类型日期加几天
     *
     * @param s
     * @param n
     * @return Date
     */
    public static Date addDay(String s, int n) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Calendar cd = Calendar.getInstance();
            cd.setTime(sdf.parse(s));
            cd.add(Calendar.DATE, n);//增加一天
            return stringToDateDefault(sdf.format(cd.getTime()));
        } catch (Exception e) {
            return null;
        }
    }
    /**
     * 获取两个日期相差的月数
     *
     * @param beginDate
     * @param endDate
     * @return
     */
    public static String month(Date beginDate, Date endDate) {
        if (beginDate == null) {
            return "";
        }
        if (endDate == null) {
            return "";
        }
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1.setTime(beginDate);
        c2.setTime(endDate);
        int year1 = c1.get(Calendar.YEAR);
        int year2 = c2.get(Calendar.YEAR);
        int month1 = c1.get(Calendar.MONTH);
        int month2 = c2.get(Calendar.MONTH);
        int day1 = c1.get(Calendar.DAY_OF_MONTH);
        int day2 = c2.get(Calendar.DAY_OF_MONTH);
        // 获取年的差值
        int yearInterval = year1 - year2;
        // 如果 d1的 月-日 小于 d2的 月-日 那么 yearInterval-- 这样就得到了相差的年数
        if (month1 < month2 || month1 == month2 && day1 < day2) {
            yearInterval--;
        }
        // 获取月数差值
        int monthInterval = (month1 + 12) - month2;
        if (day1 < day2) {
            monthInterval--;
        }
        monthInterval %= 12;
        int monthsDiff = Math.abs(yearInterval * 12 + monthInterval);
        return String.valueOf(monthsDiff);
    }

}
